from datetime import datetime, timedelta
import copy


def parse_date(date_str):
    for fmt in ('%Y/%m/%d', '%Y-%m-%d'):
        try:
            return datetime.strptime(date_str, fmt)
        except ValueError:
            continue
    raise ValueError(f"无法解析日期格式: {date_str}")


def format_date(dt, fmt='%Y/%m/%d'):
    return dt.strftime(fmt)


class TimeManager:
    def __init__(self, base_date_str, rules=None, default_structure=None):
        self.base_date = parse_date(base_date_str)
        self.rules = rules or {}
        self.default_structure = default_structure or {}  # 默认模块结构
        self.global_cache = {}  # 全局缓存所有模块的子项时间

    def apply_to_project(self, project, dry_run=True):
        """
        对单个项目应用时间规则，并自动注入缺失的模块和施工日期字段
        
        :param project: 单个项目字典
        :param dry_run: 是否只查看不修改
        :return: 修改后的项目
        """
        project = copy.deepcopy(project)

        # 创建 instance_mapping 字段（如果不存在）
        if 'instance_mapping' not in project:
            project['instance_mapping'] = {}

        # 清空全局缓存
        self.global_cache.clear()

        # 处理公共字段中的施工日期偏移
        if '施工日期' in project and '施工日期' in self.rules.get("公共字段", {}):
            base_offset = self.rules["公共字段"]["施工日期"].get("offset_days", 0)
            new_date = self.base_date + timedelta(days=base_offset)
            if not dry_run:
                project['施工日期'] = format_date(new_date)

        base_date_for_use = parse_date(project.get('施工日期'))  # 更新后的施工日期作为新基准

        instance_mapping = project['instance_mapping']

        # 第一遍：记录已有施工日期到 global_cache
        for module_name, instances in instance_mapping.items():
            for instance in instances:
                for key, sub_dict in instance.items():
                    if isinstance(sub_dict, dict) and '施工日期' in sub_dict:
                        full_key = f"{module_name}.{key}"
                        self.global_cache[full_key] = parse_date(sub_dict['施工日期'])

        # 第二遍：处理每个模块 → 注入模块 & 子项 & 时间推导
        for module_name, module_rule in self.rules.items():
            if module_name == "公共字段":
                continue

            # 模块不存在于项目中 → 注入
            if module_name not in instance_mapping:
                print(f"[注入] 模块 {module_name} 不存在于项目中，已自动添加")
                instance_mapping[module_name] = []

            instances = instance_mapping[module_name]

            date_cache = {}  # 当前模块的时间缓存

            # 第三遍：记录当前模块已有时间
            for instance in instances:
                for key, sub_dict in instance.items():
                    if isinstance(sub_dict, dict) and '施工日期' in sub_dict:
                        date_cache[key] = parse_date(sub_dict['施工日期'])
                        self.global_cache[f"{module_name}.{key}"] = date_cache[key]

            # 第四遍：注入缺失的子项（根据 default_structure）
            if module_name in self.default_structure and not dry_run:
                existing_keys = set()
                for instance in instances:
                    existing_keys.update(instance.keys())

                for sub_key in self.default_structure[module_name]:
                    if sub_key not in existing_keys:
                        print(f"[注入] 子项 {sub_key} 在模块 {module_name} 中缺失，已自动添加")
                        instances.append({sub_key: {}})

            # 第五遍：推导施工日期
            updated_instances = []
            for instance in instances:
                new_instance = copy.deepcopy(instance)
                for key, sub_dict in new_instance.items():
                    if not isinstance(sub_dict, dict):
                        continue

                    # 已有施工日期 → 缓存
                    if '施工日期' in sub_dict:
                        date_cache[key] = parse_date(sub_dict['施工日期'])
                        self.global_cache[f"{module_name}.{key}"] = date_cache[key]
                        updated_instances.append({key: sub_dict})
                        continue

                    # 查看是否有规则
                    if key in module_rule:
                        rule = module_rule[key]
                        base_key = rule.get("base_key")  # 可能为 None
                        offset_days = rule.get("offset_days", 0)

                        # 添加 None 检查
                        if base_key is None:
                            print(f"[警告] 子项 {key} 缺少 base_key 规则，使用默认基准日期")
                            base_dt = base_date_for_use
                        else:
                            if '.' in base_key:
                                ref_module, ref_key = base_key.split('.', 1)
                                base_full_key = f"{ref_module}.{ref_key}"
                            else:
                                base_full_key = f"{module_name}.{base_key}"
                            base_dt = self.global_cache.get(base_full_key, base_date_for_use)

                        calculated_date = base_dt + timedelta(days=offset_days)

                        # 插入施工日期
                        sub_dict['施工日期'] = format_date(calculated_date)
                        date_cache[key] = calculated_date
                        self.global_cache[f"{module_name}.{key}"] = calculated_date

                    updated_instances.append({key: sub_dict})

                instance_mapping[module_name] = updated_instances

        return project

    def apply_to_all_projects(self, project_list, dry_run=True):
        """
        应用规则到整个 project_list
        
        :param project_list: 原始项目列表
        :param dry_run: 是否只查看不修改
        :return: 新的项目列表
        """
        updated_project_list = []

        for project in project_list:
            updated_project = self.apply_to_project(project, dry_run=dry_run)
            updated_project_list.append(updated_project)

        return updated_project_list